#pragma once
#include "predef.h"
#include "ObjectName.h"

namespace Pattern
{	
	class ConfigSheet;

	class PATTERN_API ConfigItem
	{		
		friend class ConfigSheet;
	private:
		ObjectName name;
		ObjectName group;
		std::string value;
		ConfigSheet* host;
		
	public:
		ConfigItem();

		bool isEmpty() const;
		void Clear();

		static ConfigItem& Empty();

		bool operator ==(const ConfigItem& another) const;
		bool operator !=(const ConfigItem& another) const;

		Pattern::ObjectName Name() const;
		void Name(const Pattern::ObjectName& val);

		Pattern::ObjectName Group() const;
		void Group(const Pattern::ObjectName& val);

		std::string Value() const;
		void Value(const std::string& val);
	};

	class PATTERN_API ConfigSheet
	{
		friend class ConfigItem;
	public:
		class Listener
		{
			friend class ConfigSheet;
		protected:
			virtual void OnItemNameChanged(ConfigItem* item) = 0;
			virtual void OnItemGroupChanged(ConfigItem* item) = 0;
			virtual void OnItemValueChanged(ConfigItem* item) = 0;
		};

	private:
		typedef std::vector<ConfigItem> PropertyItemList;
		typedef std::vector<Listener*> ListenerList;
		ListenerList listeners;
		PropertyItemList itemList;
		bool NotifyItemNameChanging(const ObjectName& newName);
		void NotifyItemNameChanged(ConfigItem* item);
		void NotifyItemGroupChanged(ConfigItem* item);
		void NotifyItemValueChanged(ConfigItem* item);

	public:
		ConfigSheet(void);
		~ConfigSheet(void);

		bool Add(ConfigItem& value);
		bool Remove(const ObjectName& key);

		ConfigItem& GetByIndex(Uint index);
		ConfigItem& GetByName(const ObjectName& key);

		Uint Count() const;				
		bool ContainsName(const ObjectName& key) const;		

		bool IsEmpty() const;

		void AddListener(Listener* listener);

		void RemoveListener(Listener* listener);
	};
}